#include "bsp.h"

#define UART_COMx  UART_FIFO_COM0

#define RS485_TIMEOUT_MAX   222
#define RS485_RECV_TIMEOUT  4
#define RS485_SEND_TIMEOUT  4

#define RS485_SEND_EN()    /* 使能485发送 */
#define RS485_RECV_EN()    /* 使能485接收 */

typedef struct
{
    volatile uint8_t send_time_count;
    volatile uint8_t recv_time_count;
}rs485_t;

static rs485_t _rs485 = {0};

/***************************************************************************************************
 * @fn      rs485_send_befor
 *
 * @brief   485发送前要做的事
 *
 * @param  arg 参数
 *
 * @return  无 
 */
static void rs485_send_befor_cb(void *arg)
{
    /* 使能485发送 */
    RS485_SEND_EN();
}

/***************************************************************************************************
 * @fn      rs485_send_befor
 *
 * @brief   485每发送一个字节要做的事（在串口发送中断中执行）
 *
 * @param  arg 参数
 *
 * @return  无 
 */
static void rs485_send_ing_cb(void *arg)
{
    _rs485.send_time_count = 0;
}

/***************************************************************************************************
 * @fn      rs485_send_over_cb
 *
 * @brief   485发送完一帧后要做的事（在串口发送完成中断中执行）
 *
 * @param  arg 参数
 *
 * @return  无 
 */
static void rs485_send_over_cb(void *arg)
{
    /* 使能485接收 */
    RS485_RECV_EN();

//    _rs485.send_time_count = RS485_TIMEOUT_MAX;
}

/***************************************************************************************************
 * @fn      rs485_recv_idle_cb
 *
 * @brief   rs485对应的串口空闲时执行的（在串口空闲中断中执行）
 *
 * @param  arg 参数
 *
 * @return  无 
 */
static void rs485_recv_idle_cb(void *arg)
{

}

/***************************************************************************************************
 * @fn      rs485_recv_ing_cb
 *
 * @brief   rs485每接收一个字节要做的事（在串口空闲中断中执行）
 *
 * @param  arg 参数
 *
 * @return  无 
 */
static void rs485_recv_ing_cb(void *arg)
{
    _rs485.recv_time_count = 0;
}

/***************************************************************************************************
 * @fn      rs485_init
 *
 * @brief   485初始化
 *
 * @param   无
 *
 * @return  无 
 */
BOOL rs485_init(void)
{
    BOOL ret = FALSE;

    _rs485.recv_time_count = RS485_TIMEOUT_MAX;
    _rs485.send_time_count = RS485_TIMEOUT_MAX;

    /* 初始化485使能引脚 */

    /* 设置发送回调函数 */
    ret = uart_fifo_reg_send_cb(UART_COMx, 
                                rs485_send_befor_cb,
                                rs485_send_ing_cb,
                                rs485_send_over_cb);
    if (ret != TRUE)
    {
        return ret;
    }

    /* 设置接收回调函数 */
    ret = uart_fifo_reg_recv_cb(UART_COMx, 
                                rs485_recv_idle_cb,
                                rs485_recv_ing_cb);
    if (ret != TRUE)
    {
        return ret;
    }

    /* 初始化串口并设置波特率 */
    ret = uart_fifo_init(UART_COMx, 9600);

    return ret;
}

/***************************************************************************************************
 * @fn      rs485_is_recv_completed
 *
 * @brief   判断rs485是否接收完成
 *
 * @param   无
 *
 * @return  接收完成返回TRUE，否则返回FALSE 
 */
BOOL rs485_is_recv_completed(void)
{
    if (RS485_RECV_TIMEOUT == _rs485.recv_time_count)
    {
        return TRUE;
    }

    return FALSE;
}

/***************************************************************************************************
 * @fn      rs485_is_send_ing
 *
 * @brief   判断rs485是否正在发送
 *
 * @param   无
 *
 * @return  正在发送返回TRUE，否则返回FALSE 
 */
BOOL rs485_is_send_ing(void)
{
    if (RS485_SEND_TIMEOUT < _rs485.send_time_count)
    {
        return TRUE;
    }

    return FALSE;
}

/***************************************************************************************************
 * @fn      rs485_recv_ing
 *
 * @brief   判断rs485是否正在接收
 *
 * @param   无
 *
 * @return  正在接收返回TRUE，否则返回FALSE 
 */
BOOL rs485_is_recv_ing(void)
{
    if (RS485_RECV_TIMEOUT < _rs485.recv_time_count)
    {
        return TRUE;
    }

    return FALSE;
}


/***************************************************************************************************
 * @fn      rs485_recv_message
 *
 * @brief   获取rs485接收到的消息
 *
 * @param   buff 接收到的数据
 *
 * @return  接收到的数据个数（单位：字节） 
 */
int32_t rs485_get_message(uint8_t *buff)
{
    int32_t length;

    /* 指针参数不能为空 */
    if (NULL == buff)
    {
        return 0;
    }

    return uart_fifo_recv(UART_COMx, buff, length);  /* 从buff中获取数据 */
}

/***************************************************************************************************
 * @fn      rs485_send_message
 *
 * @brief   从rs485接口发送消息
 *
 * @param   buff 要发送的数据
 * @param   length 要发送的数据个数（单位：字节）
 *
 * @return  实际发送的数据个数（单位：字节） 
 */
int32_t rs485_send_message(uint8_t *buff, int32_t length)
{
    /* 指针参数不能为空 */
    if (NULL == buff)
    {
        return 0;
    }

    return uart_fifo_send(UART_COMx, buff, length);
}

/***************************************************************************************************
 * @fn      rs485_time_slice
 *
 * @brief   给485提供时基准
 *
 * @param   无
 *
 * @return  无 
 */
void rs485_time_slice(void)
{
    if (_rs485.recv_time_count <= RS485_TIMEOUT_MAX)
    {
        _rs485.recv_time_count++;
    }

    if (_rs485.send_time_count <= RS485_TIMEOUT_MAX)
    {
        _rs485.send_time_count++;
    }
}
